#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>

#include <asm/io.h>		/* ioremap */

#include "led_opr.h"

/* 1. Configure IOMUX to select GPIO mode
 * 2. Configure GPIO direction register to output (GPIO_GDIR[GDIR] to set 1b)
 * 3. Write value to data register(GPIO_DR)
 */

static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
static volatile unsigned int *GPIO5_GDIR                             ;
static volatile unsigned int *GPIO5_DR                               ;


/* 1. set IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 to Configure GPIO5_IO3 as GPIO
 * IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 	0x2290014
 * bit[3:0] = 0b0101
 */

/* 2. set GPIO5_GDIR to Configure GPIO5_IO03 as output
 * GPIO5_GDIR 	0x020AC000 + 4
 * bit[3] = 0b1
 */

static int board_demo_led_init(int which) /* which LED init */
{
	unsigned int val;

	if(which == 0){
		/* if GPIO5_GDIR is null */
		if(!IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3){  
            IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = ioremap(0x2290014, 4);
            GPIO5_GDIR                              = ioremap(0x020AC000 + 0x4, 4);
            GPIO5_DR                                = ioremap(0x020AC000 + 0, 4);
		}

		val = *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3;
		val &= ~(0xf);  	/* clear bit[3:0] */
		val |= (5);			/* set bit[3:0] = 0b0101 */
		*IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = val;

		*GPIO5_GDIR |= (1<<3);
	}
	return 0;
}

/* 3. set GPIO5_DR to Configure GPIO5_IO3  output 0 / 1
 * GPIO5_DR 	0x020AC000 + 0
 * bit[3] = 0b0 / 0b1
 */

static int board_demo_led_ctl(int which,char status) /* which : which LED, status:1-亮，0-灭*/
{
	if(which == 0){
		if(status){

			/* set GPIO5_DR to configure GPIO5_IO03 output 0 */
			*GPIO5_DR &= ~(1 << 3);

		}else{
		
			/* set GPIO5_DR to configure GPIO5_IO03 output 1 */
			*GPIO5_DR |= (1 << 3);
			
		}

	}
	return 0;
}

static struct  led_operations board_demo_led_opr = {
	.num  = 1,     /*控制多少个LED*/
	.init = board_demo_led_init,
	.ctl  = board_demo_led_ctl,
};

struct led_operations *get_board_led_opr(void)
{
	return &board_demo_led_opr;
}
